﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Objects.DataClasses;
using System.Data.Objects;
using System.Data;
using System.Linq.Expressions;

using SimpleForum.Data.Models;

namespace SimpleForum.Data.Repositories
{
    public class Repository<T> : IRepository<T> where T : EntityObject
    {
        protected ObjectContext Context;
        protected ObjectSet<T> Table;

        public Repository(DatabaseContextContainer SimpleForumEntities)
        {
            Context = SimpleForumEntities;
            Table = Context.CreateObjectSet<T>();
        }

        public virtual T Get(object Id)
        {
            string EntitySetName = Context.DefaultContainerName + "." + Table.EntitySet.Name;
            string KeyName = Table.EntitySet.ElementType.KeyMembers[0].ToString();
            EntityKey Key = new EntityKey(EntitySetName, new[] { new EntityKeyMember(KeyName, Id) });

            object Found;

            if (Context.TryGetObjectByKey(Key, out Found)) return (T)Found;
            else return null;
        }

        public IQueryable<T> Get()
        {
            return Table.AsQueryable();
        }

        public T Add(T Entity)
        {
            Table.AddObject(Entity);
            SaveChanges();

            return Entity;
        }

        public void Delete(int Id)
        {
            var Entity = Get(Id);
            Table.DeleteObject(Entity);

            SaveChanges();
        }

        public void Delete(T Entity)
        {
            Table.DeleteObject(Entity);
            SaveChanges();
        }

        public void Delete(IEnumerable<T> Entities)
        {
            foreach (T Entity in Entities)
            {
                Table.DeleteObject(Entity);
            }

            SaveChanges();
        }

        public T Update(T Entity)
        {
            if (Entity.EntityState == EntityState.Detached) Table.Attach(Entity);

            Table.Context.ObjectStateManager.ChangeObjectState(Entity, EntityState.Modified);
            SaveChanges();

            return Entity;
        }

        public IEnumerable<T> Where(Expression<Func<T, bool>> Where)
        {
            return Table.Where<T>(Where);
        }

        public void SaveChanges()
        {
            Table.Context.SaveChanges();
        }
    }
}